#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
@file: configuration.py
@time: 2024-07-11 06:06
@desc: 
"""
import traceback
from flask import Blueprint, request, jsonify, send_file
from io import BytesIO
import pandas as pd
from tools import log_operations, token_required
from global_scope import get_db, MAX_PAGE_SIZE, configuration_sheet_name
from common_tools import apply_formatting, to_dict
from tools import excel_to_configurations
from datetime import datetime
from project_model import Configuration, Image

db = get_db()
conf_bp = Blueprint('config', __name__, url_prefix='/configurations')


@conf_bp.route('', methods=['POST'])
@log_operations
@token_required
def create_configuration():
    data = request.json
    name = data.get('name')
    value = data.get('value')
    remark = data.get('remark')

    if not name:
        return jsonify({"code": 1, "message": "Name is required"}), 400

    new_config = Configuration(name=name, value=value, remark=remark)
    db.session.add(new_config)
    db.session.commit()
    return jsonify({"code": 0, "message": "OK", "data": new_config.id, "originUrl": request.url}), 200


@conf_bp.route('/<int:config_id>', methods=['DELETE'])
@log_operations
@token_required
def delete_configuration(config_id):
    config = Configuration.query.get_or_404(config_id)
    db.session.delete(config)
    db.session.commit()
    return jsonify({"code": 0, "message": "OK", "data": config_id, "originUrl": request.url}), 200


@conf_bp.route('/<int:config_id>', methods=['PATCH'])
@log_operations
@token_required
def update_configuration(config_id):
    data = request.json
    config = Configuration.query.get_or_404(config_id)
    config.name = data.get('name', config.name)
    config.value = data.get('value', config.value)
    config.remark = data.get('remark', config.remark)
    config.updateTime = datetime.utcnow()
    if 'images' in data:
        image_ids = [c.get('id') for c in data['images'] if c.get('id')]
        images = Image.query.filter(Image.id.in_(image_ids)).all()
        config.images = images
    db.session.commit()
    return jsonify({"code": 0, "message": "OK", "data": config_id, "originUrl": request.url}), 200


@conf_bp.route('/<int:config_id>', methods=['GET'])
@log_operations
@token_required
def get_configuration(config_id):
    config = Configuration.query.get_or_404(config_id)
    return jsonify({"code": 0, "message": "OK", "data": config.to_dict(), "originUrl": request.url}), 200


@conf_bp.route('', methods=['GET'])
@log_operations
@token_required
def list_configurations():
    page = request.args.get('page', 1, type=int)
    page_size = min(request.args.get('pageSize', MAX_PAGE_SIZE, type=int), MAX_PAGE_SIZE)
    name = request.args.get('name', '', type=str)
    value = request.args.get('value', '', type=str)
    remark = request.args.get('remark', '', type=str)

    query = Configuration.query
    if name:
        query = query.filter(Configuration.name.contains(name))
    if value:
        query = query.filter(Configuration.value.contains(value))
    if remark:
        query = query.filter(Configuration.remark.contains(remark))

    pagination = query.paginate(page=page, per_page=page_size, error_out=False)
    configs = pagination.items
    response_data = [
        to_dict(
            images=[to_dict(id=img.id, imageUrl=img.imageUrl) for img in config.images],
            name=config.name, value=config.value, remark=config.remark, id=config.id,
        ) for config in configs
    ]
    return jsonify({
        "code": 0,
        "message": "OK",
        "data": response_data,
        "originUrl": request.url,
        "total": pagination.total,
        "pages": pagination.pages,
        "current_page": pagination.page
    }), 200


@conf_bp.route('/download', methods=['GET'])
@log_operations
@token_required
def download_configurations():
    output = BytesIO()
    with pd.ExcelWriter(output, engine='openpyxl') as writer:
        df = pd.read_sql(Configuration.query.statement, db.session.bind)
        df.to_excel(writer, index=False, sheet_name=configuration_sheet_name)
        apply_formatting(writer.sheets[configuration_sheet_name], df)
    output.seek(0)
    return send_file(output, download_name="configurations.xlsx", as_attachment=True)


@conf_bp.route('/upload', methods=['POST'])
@log_operations
@token_required
def upload_configurations():
    if 'file' not in request.files:
        return jsonify({"code": 1, "message": "No file part"}), 400

    file = request.files['file']
    if file.filename == '':
        return jsonify({"code": 1, "message": "No selected file"}), 400

    try:
        new_records, updated_records = excel_to_configurations(file, request)
        return jsonify({
            "code": 0,
            "message": f"Configurations uploaded successfully: {new_records} added, {updated_records} updated"
        }), 201
    except Exception as e:
        tb = traceback.format_exc()
        request.trace_logger.error(f"Exception occurred: {str(e)}\n{tb}")
        return jsonify({"code": 1, "message": str(e)}), 500
